package vns.client.view;

import java.util.ArrayList;
import java.util.List;

import vns.client.helper.Helper;
import vns.client.presenter.ObjectPropertyTypePresenter;
import vns.shared.ObjectPropertyTypeDTO;
import vns.shared.ObjectTypeDTO;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTMLPanel;

public class ObjectPropertyTypeUI extends Composite implements
		ObjectPropertyTypePresenter.Display {

	private List<String> listStringColumn = new ArrayList<String>();
	private List<String> listStringBaseType = new ArrayList<String>();
	private List<ObjectPropertyTypeDTO> listBaseType = new ArrayList<ObjectPropertyTypeDTO>();
	private List<ObjectPropertyTypeDTO> listRow = new ArrayList<ObjectPropertyTypeDTO>();
	private List<ObjectTypeDTO> listOType = new ArrayList<ObjectTypeDTO>();

	private static int rowSelectedID;

	private static ObjectPropertyTypeUIUiBinder uiBinder = GWT
			.create(ObjectPropertyTypeUIUiBinder.class);
	@UiField
	FlexTable flexTableObjectPropertyType;
	@UiField
	HTMLPanel htmlPanelObjectPropertyType;
	@UiField
	Button btAdd;
	@UiField
	Button btDel;
	@UiField
	Button btUpdate;

	interface ObjectPropertyTypeUIUiBinder extends
			UiBinder<Widget, ObjectPropertyTypeUI> {
	}

	/*
	 * Constructor
	 */
	public ObjectPropertyTypeUI() {
		initWidget(uiBinder.createAndBindUi(this));
		bind();
	}

	private void bind() {
		listStringColumn.clear();
		listStringColumn.add("");
		listStringColumn.add("Tên thuộc tính");
		listStringColumn.add("Kiểu cơ bản");
		listStringColumn.add("Kiểu đối tượng");
		listStringColumn.add("Mô tả");

		flexTableObjectPropertyType.setBorderWidth(1);
		flexTableObjectPropertyType.setCellPadding(2);
		flexTableObjectPropertyType.setCellSpacing(0);
		
		flexTableObjectPropertyType.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				getClickedRow(event);
			}
		});
		
		/*
		 * Danh sách các kiểu cơ bản 
		 */
		listStringBaseType.add("Boolean");
		listStringBaseType.add("Datetime");
		listStringBaseType.add("String");
		listStringBaseType.add("Text");
		listStringBaseType.add("Float");
		listStringBaseType.add("GoogleAccount");
		listStringBaseType.add("Integer");
		listStringBaseType.add("Link");
		listStringBaseType.add("PostalAddress");
		listStringBaseType.add("Rating");
		listStringBaseType.add("File");
		listStringBaseType.add("Image");
		listStringBaseType.add("Password");
		
		listBaseType.clear();
		for(int i = 0; i < listStringBaseType.size(); i++){
			ObjectPropertyTypeDTO o = new ObjectPropertyTypeDTO(null, listStringBaseType.get(i), null, listStringBaseType.get(i), "Kiểu cơ bản");
			listBaseType.add(o);
		}
	}

	public Widget asWidget() {
		return this;
	}

	public int getClickedRow(ClickEvent event) {
		int selectedRow = -1;
		HTMLTable.Cell cell = flexTableObjectPropertyType
				.getCellForEvent(event);
		if (cell != null) {
			if (cell.getCellIndex() >= 0) {
				selectedRow = cell.getRowIndex();
			}
		}
		swapClickedRow(selectedRow, cell.getCellIndex());
		return selectedRow;
	}

	public void renderClickedRow() {
		if (rowSelectedID > 0) {
			HTMLTable.RowFormatter rf = flexTableObjectPropertyType.getRowFormatter();
			rf.addStyleName(rowSelectedID, "vnsClickedRow");
		}
	}

	public void unrenderClickedRow() {
		if (rowSelectedID > 0) {
			HTMLTable.RowFormatter rf = flexTableObjectPropertyType.getRowFormatter();
			rf.removeStyleName(rowSelectedID, "vnsClickedRow");
		}
	}	
	private void swapClickedRow(int rowNow, int cellindex) {
		if (rowNow != rowSelectedID && rowNow>0) {
			unrenderClickedRow();
			setRowEnable(rowSelectedID, false);
			rowSelectedID = rowNow;
			
			renderClickedRow();
			setRowEnable(rowSelectedID, true);
//			Window.alert("Hàng chọn bây giờ: "
//					+ Integer.toString(rowSelectedID));
		} else if(rowNow == rowSelectedID && rowNow > 0){
			if(cellindex==0){
				unrenderClickedRow();
				setRowEnable(rowSelectedID, false);
				rowSelectedID = -1;
			}
		}
	}

	private void initTableFirst() {
		flexTableObjectPropertyType.clear();
		/*
		 * Tên các cột
		 */
		int i = 0;
		for (final String columnName : listStringColumn) {
			flexTableObjectPropertyType.setHTML(0, i, "<center><b>"
					+ columnName + "</b></center>");
			i++;
		}
		
		/*
		 * Các kiểu cơ bản
		 */
		if(this.listRow.size()<listStringBaseType.size()){
			for(i = this.listRow.size(); i<listStringBaseType.size();i++){
				
			}
		}
	}

	/*
	 * Set Row Enable
	 */
	private void setRowEnable(int row, boolean value) {
		if (row <= flexTableObjectPropertyType.getRowCount() - 1 && row > 0) {
			CheckBox orderCheckBox = (CheckBox) flexTableObjectPropertyType.getWidget(row, 0);
			orderCheckBox.setValue(value);
			TextBox nameTextBox = (TextBox) flexTableObjectPropertyType
					.getWidget(row, 1);
			nameTextBox.setReadOnly(!value);
			ListBox otid = (ListBox) flexTableObjectPropertyType.getWidget(row,
					3);
			otid.setEnabled(value);
			TextBox desTextBox = (TextBox) flexTableObjectPropertyType
					.getWidget(row, 4);
			desTextBox.setReadOnly(!value);
		}
	}
	
	/*
	 * Create Otype CheckBox 
	 */
	private ListBox CreateObjectTypeListBox(String oTypeID){
		ListBox lb = new ListBox();
		lb.addItem(" -- Chọn danh sách -- ","");
		int i = 1;
//		Window.alert("UI CreateObjectTypeListBox ListOType = " + Integer.toString(this.listOType.size()));
//		if(oTypeID.trim()!=null) Window.alert("Duoc load: " + oTypeID);
		if (oTypeID != null) {
			oTypeID = oTypeID.trim();
			for (ObjectTypeDTO o : this.listOType) {
				String tempID = KeyFactory.keyToString(o.getId());
				tempID = tempID.trim();
				lb.addItem(o.getName().trim(), tempID);
				if (oTypeID.compareTo(tempID) == 0) {
					// Window.alert("So sanh (true):" + o.getName());
					lb.setSelectedIndex(i);
				}
				i++;
			}
		} else {
			for (ObjectTypeDTO o : this.listOType) {
				String tempID = KeyFactory.keyToString(o.getId());
				lb.addItem(o.getName().trim(), tempID.trim());
				i++;
			}
		}
		return lb;
	}
	
	
	/*
	 * **************************************************************************************
	 */

	/*
	 * Add Row with Wiget
	 */
	private int addRow(Widget nameTextbox, String typeString,
			Widget otypeidListbox, Widget desTextbox) {
		int row = flexTableObjectPropertyType.getRowCount();
		if(row<listStringBaseType.size()+1){
			otypeidListbox.setVisible(false);
		}
		CheckBox tempCheckbox = new CheckBox();
		tempCheckbox.setText(Integer.toString(row));
		flexTableObjectPropertyType.setWidget(row, 0, tempCheckbox);
		flexTableObjectPropertyType.setWidget(row, 1, nameTextbox);
		flexTableObjectPropertyType.setText(row, 2, typeString);
		flexTableObjectPropertyType.setWidget(row, 3, otypeidListbox);
		flexTableObjectPropertyType.setWidget(row, 4, desTextbox);
		setRowEnable(row, false);
		return row;
	}

	/*
	 * Add Row with data
	 */
	private int addRow(String name, String type, String otypeID, String des) {
		int row = flexTableObjectPropertyType.getRowCount();

		TextBox nameTextBox = new TextBox();
		nameTextBox.setValue(name);

		ListBox otypeidListBox = CreateObjectTypeListBox(otypeID);
		
		TextBox desTextBox = new TextBox();
		desTextBox.setValue(des);
		
		addRow(nameTextBox, type, otypeidListBox, desTextBox);
		setRowEnable(row, false);

		return row;
	}

	/*
	 * Add Row Empty
	 */
	private int addRow() {
		ListBox listboxObjectPropertyType = CreateObjectTypeListBox(null);
		int row = addRow(new TextBox(), "Key", listboxObjectPropertyType, new TextBox());
		setRowEnable(row, false);
		return row;
	}

	/*
	 * Remove selected Row
	 */
	private void removeRow() {
		if (rowSelectedID <= -1)
			Window.alert("Chọn hàng cần xóa!");
		else if (rowSelectedID > 0) {
			flexTableObjectPropertyType.removeRow(rowSelectedID);
			int remvIndex = Helper.getIndexByRow(rowSelectedID, listRow.size());
			if(remvIndex!=-1){
				listRow.remove(remvIndex);
			}
			rowSelectedID = -1;
		} else 
			Window.alert("Không xóa kiểu cơ bản!");
	}
	
	/*
	 * Update all rows
	 */
	private void updateRow() {
//		Window.alert("Update row in UI");
		for (int index = 0; index < listRow.size() ; index++) {
			int row = Helper.getRowByIndex(index, flexTableObjectPropertyType.getRowCount());

			TextBox nameTextBox = (TextBox) flexTableObjectPropertyType
					.getWidget(row, 1);
			String s = flexTableObjectPropertyType.getText(row, 2);
			ListBox lb = (ListBox) flexTableObjectPropertyType.getWidget(row, 3);
			
			String temp = lb.getValue(lb.getSelectedIndex());
			
			if(temp.compareTo("")==0) 
				temp = null;
			else
				temp = temp.trim();
			
			TextBox desTextBox = (TextBox) flexTableObjectPropertyType
					.getWidget(row, 4);
			
			listRow.get(index).setName(nameTextBox.getValue());
			listRow.get(index).setOtype(temp);
			listRow.get(index).setBaseType(s);
			listRow.get(index).setDescribe(desTextBox.getValue());

//			if(temp.compareTo("")!=0) Window.alert("Duoc luu " + temp + "["+lb.getItemText(lb.getSelectedIndex()));

		}
//		Window.alert("Số dòng trong bảng : " + Integer.toString(flexTableObjectPropertyType.getRowCount()));
//		Window.alert("Số đối tượng : " + Integer.toString(listRow.size()));
		
		if (flexTableObjectPropertyType.getRowCount() - 1 > listRow.size()) {
			for (int row = listRow.size()+1; row < flexTableObjectPropertyType
					.getRowCount(); row++) {
				ListBox lb = (ListBox)flexTableObjectPropertyType.getWidget(row, 3);
				String temp = lb.getValue(lb.getSelectedIndex());
				ObjectPropertyTypeDTO o = new ObjectPropertyTypeDTO(
						null,
						flexTableObjectPropertyType.getText(row, 2),
						temp.trim(),
						((TextBox) flexTableObjectPropertyType.getWidget(row, 1)).getValue(),
						((TextBox) flexTableObjectPropertyType.getWidget(row, 4)).getValue());
				listRow.add(o);
			}
		}
	}
	
	/*
	 * Event
	 */

	@UiHandler("btAdd")
	void onBtAddClick(ClickEvent event) {
		addRow();
	}

	@UiHandler("btDel")
	void onBtDelClick(ClickEvent event) {
		removeRow();
	}

	@UiHandler("btUpdate")
	void onBtUpdateClick(ClickEvent event) {
		updateRow();
	}

	
	/*
	 * Implement Presenter
	 */

	@Override
	public List<ObjectTypeDTO> getListOType() {
		return listOType;
	}

	@Override
	public void setListOType(List<ObjectTypeDTO> listOType) {
		this.listOType.clear();
		this.listOType.addAll(listOType);
//		Window.alert("UI ListOType = " + Integer.toString(this.listOType.size()));
	}

	@Override
	public Button getUpdateButton() {
		return btUpdate;
	}

	@Override
	public Button getRemoveButton() {
		return btDel;
	}

	@Override
	public ArrayList<ObjectPropertyTypeDTO> getListRow() {
		return (ArrayList<ObjectPropertyTypeDTO>)this.listRow;
	}

	@Override
	public boolean setListRow(List<ObjectPropertyTypeDTO> listRow) {
		this.listRow = listRow;
		return true;
	}

	@Override
	public void render() {
		rowSelectedID = -1;
		initTableFirst();
		if (this.listRow.size() == 0) {
			listRow.addAll(this.listBaseType);
		}
		for (final ObjectPropertyTypeDTO objectPropertyType : this.listRow) {
			addRow(	objectPropertyType.getName(),
					objectPropertyType.getBaseType(),
					objectPropertyType.getOtype(),
					objectPropertyType.getDescribe());
		}
	}
}
